﻿using System.IO;
using Spine.Unity;
using UnityEditor;
using UnityEngine;

namespace Learning.Spine
{
    public static class SpineAnimationImport
    {
        /// <summary>
        /// 导入 Spine 动画的资源为场景使用的预制和UI使用的预制
        /// </summary>
        [MenuItem("Spine/Import Spine Animation")]
        public static void ImportSpineAnimation()
        {
            const string resPath = "Assets/Spine/Runtime/Res/SpineRes";
            const string prefabPath = "Assets/Spine/Runtime/Res/Prefab";
            const string uiPrefabPath = "Assets/Spine/Runtime/Res/UIPrefab";
            
            var dirs = Directory.GetDirectories(resPath, "*", SearchOption.TopDirectoryOnly);
            foreach (var dir in dirs)
            {
                var name = Path.GetFileName(dir);
                var prefabName = Path.Combine(prefabPath, name + ".prefab");
                var uiPrefabName = Path.Combine(uiPrefabPath, name + ".prefab");
                ImportToPrefab(dir, prefabName, uiPrefabName);
            }
            
            EditorUtility.DisplayDialog("Spine", "Import Spine Animation Complete!", "OK");
        }

        private static void ImportToPrefab(string dir, string prefabName, string uiPrefabName)
        {
            ImportSkeleton(dir);
            ImportTexture(dir);
            ImportMaterial(dir);
            
            GeneratePrefab(dir, prefabName);
            GenerateUIPrefab(dir, uiPrefabName);
        }

        private static void ImportSkeleton(string dir)
        {
            var files = Directory.GetFiles(dir, "*.skel", SearchOption.TopDirectoryOnly);
            foreach (var file in files)
            {
                var newFile = Path.ChangeExtension(file, ".skel.bytes");
                if (File.Exists(newFile))
                {
                    File.Delete(newFile);
                }
                File.Move(file, newFile);
            }
        }

        private static void ImportTexture(string dir)
        {
            var files = Directory.GetFiles(dir, "*.png", SearchOption.TopDirectoryOnly);
            foreach (var file in files)
            {
                var textureImporter = AssetImporter.GetAtPath(file) as TextureImporter;
                if (textureImporter != null)
                {
                    textureImporter.sRGBTexture = true;
                    textureImporter.wrapMode = TextureWrapMode.Clamp;

                    var platformAndroid = textureImporter.GetPlatformTextureSettings("Android");
                    if (platformAndroid != null)
                    {
                        platformAndroid.format = TextureImporterFormat.ASTC_4x4;
                        platformAndroid.overridden = true;
                        textureImporter.SetPlatformTextureSettings(platformAndroid);
                    }
                    
                    var platformIPhone = textureImporter.GetPlatformTextureSettings("iPhone");
                    if (platformIPhone != null)
                    {
                        platformIPhone.format = TextureImporterFormat.ASTC_4x4;
                        platformIPhone.overridden = true;
                        textureImporter.SetPlatformTextureSettings(platformIPhone);
                    }
                    
                    textureImporter.SaveAndReimport();
                }
            }
        }

        private static void ImportMaterial(string dir)
        {
            var files = Directory.GetFiles(dir, "*.mat", SearchOption.TopDirectoryOnly);
            foreach (var file in files)
            {
                var material = AssetDatabase.LoadAssetAtPath<Material>(file);
                if (material != null)
                {
                    material.shader = Shader.Find("Spine/Skeleton Tint");
                    material.SetInt("_StraightAlphaInput", 1);

                    EditorUtility.SetDirty(material);
                    AssetDatabase.SaveAssetIfDirty(material);
                }
            }
        }

        private static void GeneratePrefab(string dir, string prefabName)
        {
            var name = Path.GetFileNameWithoutExtension(prefabName);
            
            var prefab = new GameObject(name);
            prefab.layer = LayerMask.NameToLayer("Spine");

            var meshRenderer = prefab.AddComponent<MeshRenderer>();
            var skeletonAnimation = prefab.AddComponent<SkeletonAnimation>();

            var skeletonDataAssetPaths = Directory.GetFiles(dir, "*_SkeletonData.asset", SearchOption.TopDirectoryOnly);
            if (skeletonDataAssetPaths.Length > 0)
            {
                var skeletonDataAsset = AssetDatabase.LoadAssetAtPath<SkeletonDataAsset>(skeletonDataAssetPaths[0]);
                if (skeletonDataAsset != null)
                {
                    skeletonAnimation.skeletonDataAsset = skeletonDataAsset;
                }
                else
                {
                    Debug.LogError("Failed to load SkeletonDataAsset at: " + dir);
                    return;
                }
            }
            else
            {
                Debug.LogError("No SkeletonDataAsset files found in folder: " + dir);
                return;
            }

            skeletonAnimation.timeScale = 1f;
            skeletonAnimation.Update(Time.unscaledDeltaTime);
            skeletonAnimation.UnscaledTime = true;

            meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
            meshRenderer.lightProbeUsage = UnityEngine.Rendering.LightProbeUsage.Off;
            meshRenderer.allowOcclusionWhenDynamic = false;

            PrefabUtility.SaveAsPrefabAsset(prefab, prefabName);
            GameObject.DestroyImmediate(prefab);

            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }

        private static void GenerateUIPrefab(string dir, string prefabName)
        {
            var name = Path.GetFileNameWithoutExtension(prefabName);
            
            var prefab = new GameObject(name);
            prefab.layer = LayerMask.NameToLayer("UI");
            
            var skeletonGraphic = prefab.AddComponent<SkeletonGraphic>();
            
            var skeletonDataAssetPaths = Directory.GetFiles(dir, "*_SkeletonData.asset", SearchOption.TopDirectoryOnly);
            if (skeletonDataAssetPaths.Length > 0)
            {
                var skeletonDataAsset = AssetDatabase.LoadAssetAtPath<SkeletonDataAsset>(skeletonDataAssetPaths[0]);
                if (skeletonDataAsset != null)
                {
                    skeletonGraphic.skeletonDataAsset = skeletonDataAsset;
                }
                else
                {
                    Debug.LogError("Failed to load SkeletonDataAsset at: " + dir);
                    return;
                }
            }
            else
            {
                Debug.LogError("No SkeletonDataAsset files found in folder: " + dir);
                return;
            }
            
            skeletonGraphic.timeScale = 1f;
            skeletonGraphic.Update(Time.unscaledDeltaTime);
            skeletonGraphic.UnscaledTime = true;

            PrefabUtility.SaveAsPrefabAsset(prefab, prefabName);
            GameObject.DestroyImmediate(prefab);

            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }
    }
}
